package com.hhd.form.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.hhd.base.utils.CommonUtils;
import com.hhd.form.entity.*;
import com.hhd.form.mapper.DesignFormMapper;
import com.hhd.form.service.*;
import com.hhd.form.table.AutoTableCreator;
import com.hhd.form.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class DesignFormServiceImpl implements IDesignFormService {
    @Autowired
    DesignFormMapper designFormMapper;

    @Autowired
    IDesignFormDefinitionService formService;

    @Autowired
    IDesignFormViewDefinitionService formViewService;

    @Autowired
    IDesignFormFieldDefinitionService formFieldService;

    @Autowired
    IDesignFormViewDefinitionService viewService;

    @Autowired
    IDesignFormActionDefinitionService actionService;

    @Autowired
    IDesignFormFieldActionDefinitionService fieldActionService;

    @Autowired
    IDesignSubFormActionDefinitionService subFormActionService;

    @Autowired
    IDesignFormMenuService menuService;

    @Autowired
    IDesignFormMenuShowFieldService menuShowFieldService;

    @Autowired
    IDesignFormMenuOrderFieldService menuOrderFieldService;

    @Autowired
    IDesignFormMenuSearchFieldService menuSearchFieldService;

    @Autowired
    IDesignFormMenuSearchQueryService menuSearchQueryService;

    @Autowired
    AutoTableCreator tableCreator;

    @Override
    @Transactional
    public void save(FormDefinition formDefinition) {
        formDefinition.setAppId("test-app");
        tableCreator.patchTable(formDefinition);

        saveFormMainDefinition(formDefinition);
        saveSubFormDefinitions(formDefinition);
        saveActions(formDefinition);
        saveMenus(formDefinition);
    }

    private void saveMenus(FormDefinition formDefinition) {
        menuService.lambdaUpdate().eq(DesignFormMenu::getFormId, formDefinition.getId()).remove();
        menuShowFieldService.lambdaUpdate().eq(DesignFormMenuShowField::getFormId, formDefinition.getId()).remove();
        menuOrderFieldService.lambdaUpdate().eq(DesignFormMenuOrderField::getFormId, formDefinition.getId()).remove();
        menuSearchFieldService.lambdaUpdate().eq(DesignFormMenuSearchField::getFormId, formDefinition.getId()).remove();
        menuSearchQueryService.lambdaUpdate().eq(DesignFormMenuSearchQuery::getFormId, formDefinition.getId()).remove();

        List<FormMenu> menus = formDefinition.getMenus();
        int count = 1;
        if (CommonUtils.isEmpty(menus)) return;
        for (FormMenu menu : menus) {
            menu.setFormId(formDefinition.getId());
            menu.setSort(count++);
            saveMenu(menu);
        }
    }

    private void saveMenu(FormMenu menu) {
        int count = 1;
        menuService.saveOrUpdate(menu);
        List<ShowField> showFields = menu.getShowFields();
        if (!CommonUtils.isEmpty(showFields)) {
            for (ShowField showField : showFields) {
                showField.setFormId(menu.getFormId());
                showField.setFormMenuId(menu.getId());
                showField.setSort(count++);
                menuShowFieldService.saveOrUpdate(showField);
            }
        }

        count = 1;
        List<OrderField> orderFields = menu.getOrderFields();
        if (!CommonUtils.isEmpty(orderFields)) {
            for (OrderField orderField : orderFields) {
                orderField.setFormId(menu.getFormId());
                orderField.setFormMenuId(menu.getId());
                orderField.setSort(count++);
                menuOrderFieldService.save(orderField);
            }
        }

        count = 1;
        List<SearchField> searchFields = menu.getSearchFields();
        if (!CommonUtils.isEmpty(searchFields)) {
            for (SearchField searchField : searchFields) {
                searchField.setFormId(menu.getFormId());
                searchField.setFormMenuId(menu.getId());
                searchField.setSort(count++);
                menuSearchFieldService.saveOrUpdate(searchField);
            }
        }
        count = 1;
        List<SearchQuery> searchQuerys = menu.getSearchQuerys();
        if (!CommonUtils.isEmpty(searchQuerys)) {
            for (SearchQuery searchQuery : searchQuerys) {
                searchQuery.setFormId(menu.getFormId());
                searchQuery.setFormMenuId(menu.getId());
                searchQuery.setSort(count++);
                menuSearchQueryService.saveOrUpdate(searchQuery);
            }
        }
    }

    private void saveActions(FormDefinition formDefinition) {
        actionService.lambdaUpdate().eq(DesignFormActionDefinition::getFormId, formDefinition.getId()).remove();
        fieldActionService.lambdaUpdate().eq(DesignFormFieldActionDefinition::getFormId, formDefinition.getId()).remove();
        subFormActionService.lambdaUpdate().eq(DesignSubFormActionDefinition::getFormId, formDefinition.getId()).remove();

        List<FormAction> actions = formDefinition.getActions();
        if (CommonUtils.isEmpty(actions)) return;
        int count = 1;
        for (FormAction formAction : actions) {
            formAction.setFormId(formDefinition.getId());
            if (CommonUtils.isEmpty(formAction.getId())) formAction.setId(IdWorker.getIdStr());

            formAction.setSort(count++);
            saveAction(formAction);
        }
    }

    private void saveAction(FormAction formAction) {
        actionService.saveOrUpdate(formAction);
        List<DesignFormFieldActionDefinition> fieldActions = formAction.getFieldActions();
        List<DesignSubFormActionDefinition> subFormActions = formAction.getSubFormActions();

        if (!CommonUtils.isEmpty(fieldActions)) {
            int count = 1;
            for (DesignFormFieldActionDefinition fieldAction : fieldActions) {
                fieldAction.setActionId(formAction.getId());
                fieldAction.setFormId(formAction.getFormId());
                fieldAction.setSort(count++);
                fieldActionService.saveOrUpdate(fieldAction);
            }
        }
        if (!CommonUtils.isEmpty(subFormActions)) {
            int count = 1;
            for (DesignSubFormActionDefinition subFormAction : subFormActions) {
                subFormAction.setActionId(formAction.getId());
                subFormAction.setFormId(formAction.getFormId());
                subFormAction.setSort(count++);
                subFormActionService.saveOrUpdate(subFormAction);
            }
        }
    }

    private void saveSubFormDefinitions(FormDefinition fomDefinition) {
        int sort = 1;
        List<SubFormDefinition> subForms = fomDefinition.getSubForms();
        if (!CommonUtils.isEmpty(subForms)) {
            for (SubFormDefinition subForm : subForms) {
                subForm.setAppId(fomDefinition.getAppId());
                subForm.setSort(sort++);
                subForm.setParentId(fomDefinition.getId());
                this.saveFormMainDefinition(subForm);
            }
        }
    }

    private void saveFormMainDefinition(FormDefinition fomDefinition) {
        formService.saveOrUpdate(fomDefinition);
        formViewService.lambdaUpdate().eq(DesignFormViewDefinition::getFormId, fomDefinition.getId())
                .set(DesignFormViewDefinition::getDel, true).update();
        List<DesignFormViewDefinition> views = fomDefinition.getViews();
        if (!CommonUtils.isEmpty(views)) {
            int count = 1;
            for (DesignFormViewDefinition view : views) {
                view.setDel(false);
                view.setFormId(fomDefinition.getId());
                view.setSort(count++);
            }
            formViewService.saveOrUpdateBatch(fomDefinition.getViews());
        }

        formFieldService.lambdaUpdate().eq(DesignFormFieldDefinition::getFormId, fomDefinition.getId()).remove();
        List<DesignFormFieldDefinition> fields = fomDefinition.getFields();
        int count = 1;
        if (!CommonUtils.isEmpty(fields)) {
            for (DesignFormFieldDefinition field : fields) {
                field.setFormId(fomDefinition.getId());
                field.setSort(count++);
            }
            formFieldService.saveOrUpdateBatch(fields);
        }
    }
}
